#include "decodethread.h"
#include "libavformat/avio.h"

DecodeThread::DecodeThread(AVPacketQueue *packet_queue, AVFrameQueue *frame_queue)
    : packet_queue_(packet_queue), frame_queue_(frame_queue)
{

}

DecodeThread::~DecodeThread()
{
    if(thread_) {
        Stop();
    }
    avcodec_close(codec_ctx_);
}

int DecodeThread::Init(AVCodecParameters *par)
{
    if(!par) {
        qDebug() <<" DecodeThread::Init par is NULL"<< "";
        return -1;
    }
    codec_ctx_ = avcodec_alloc_context3(NULL);
    int ret = avcodec_parameters_to_context(codec_ctx_, par);
    if(ret != 0) {
        av_strerror(ret, err2str, sizeof(err2str));
        qDebug() <<" avcodec_alloc_context3 err : "<< err2str;
        return -1;
    }

    const AVCodec *codec = avcodec_find_decoder(codec_ctx_->codec_id);
    if(!codec) {
        qDebug() <<" avcodec_find_decoder err : ";
        return -1;
    }

    ret = avcodec_open2(codec_ctx_, codec, NULL);
    if(ret != 0) {
        av_strerror(ret, err2str, sizeof(err2str));
        qDebug() <<" avcodec_open2 err : "<< err2str;
        return -1;
    }
    qDebug() <<" DecodeThread::Init finish ";

    return 0;
}

int DecodeThread::Start()
{
    thread_ = new std::thread(&DecodeThread::Run, this);
    if(!thread_) {
        qDebug() <<" new std::thread(&DecodeThread::Run, this) err : ";
        return -1;
    }

    return 0;
}

int DecodeThread::Stop()
{
    Thread::Stop();
    return 0;
}

void DecodeThread::Run()
{
    AVFrame *frame = av_frame_alloc();

    while (abort_ != 1) {
        if(frame_queue_->Size() > 10) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            continue;
        }

        AVPacket *pkt = packet_queue_->Pop(10);
        if(pkt) {
            int ret = avcodec_send_packet(codec_ctx_, pkt);
            av_packet_free(&pkt);
            if(ret < 0) {
                av_strerror(ret, err2str, sizeof(err2str));
                qDebug() <<" avcodec_open2 err : "<< err2str;
                break;
            }
            //读取解码后的帧
            forever {
                ret = avcodec_receive_frame(codec_ctx_, frame);
                if(ret == 0) {
                    frame_queue_->Push(frame);
                    qDebug() <<"frame name: " << codec_ctx_->codec->name << " frame_queue_ size: "<< frame_queue_->Size();
                    continue;
                } else if(AVERROR(EAGAIN) == ret) {
                    break;
                } else {
                    abort_ = 1;
                    av_strerror(ret, err2str, sizeof(err2str));
                    qDebug() <<" avcodec_receive_frame err : "<< err2str;
                    break;
                }
            }
        } else {
//            qDebug() <<" not got packet ";
        }
    }
}
